package cn.sourcespro.shiro.service.impl;

import cn.sourcespro.shiro.dao.SysPermissionMapper;
import cn.sourcespro.shiro.entity.SysPermission;
import cn.sourcespro.shiro.service.ShiroService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * security
 *
 * @author zhanghaowei
 * @date 2018/7/13
 */
@Service
public class ShiroServiceImpl implements ShiroService {

    private static final Logger logger = LoggerFactory.getLogger(ShiroServiceImpl.class);

    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    /**
     * 初始化权限
     * @return
     */
    @Override
    public Map<String, String> loadFilterChainDefinitions() {
        List<SysPermission> permissionList = sysPermissionMapper.selectAll(null);

        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        if (CollectionUtils.isNotEmpty(permissionList)) {
            logger.info("从数据库加载权限配置，配置数量：{}个", permissionList.size());
            for (SysPermission permission : permissionList) {
                filterChainDefinitionMap.put(permission.getUrl(), permission.getPerms());
            }
        } else {
            logger.info("系统权限未配置");
        }

        logger.info("加载默认swagger-ui权限配置");
        filterChainDefinitionMap.put("/csrf", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/v2/api-docs/**", "anon");
        filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");

        logger.info("加载默认登录/登出权限配置");
        filterChainDefinitionMap.put("/login", "anon");
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout", "anon");
        filterChainDefinitionMap.put("/**", "authc");
//        filterChainDefinitionMap.put("/**", "authc");
        return filterChainDefinitionMap;

    }

    /**
     * 在对角色进行增删改操作时，需要调用此方法进行动态刷新
     * @param shiroFilterFactoryBean
     */
    @Override
    public void updatePermission(ShiroFilterFactoryBean shiroFilterFactoryBean) {
        logger.info("动态更新权限：开始");
        synchronized (this) {
            AbstractShiroFilter shiroFilter;
            try {
                shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
            } catch (Exception e) {
                throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");
            }

            PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
            DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();

            logger.info("动态更新权限：清空老的权限控制");
            manager.getFilterChains().clear();

            shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
            shiroFilterFactoryBean.setFilterChainDefinitionMap(loadFilterChainDefinitions());
            logger.info("动态更新权限：重新构建生成");
            Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
            for (Map.Entry<String, String> entry : chains.entrySet()) {
                String url = entry.getKey();
                String chainDefinition = entry.getValue().trim().replace(" ", "");
                manager.createChain(url, chainDefinition);
            }
            logger.info("动态更新权限：完成");
        }

    }
}
